
using Abp.Application.Services.Dto;
using Abp.Authorization;
using Abp.AutoMapper;
using Abp.Linq.Extensions;
using Abp.Extensions;
using Abp.Domain.Repositories;
using L._52ABP.Application.Dtos;
using L._52ABP.Common.Extensions.Enums;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Linq.Dynamic.Core;
using System.Threading.Tasks;
using LTMCompanyName.YoyoCmsTemplate.Exam;
using LTMCompanyName.YoyoCmsTemplate.Exam.Dtos;
using LTMCompanyName.YoyoCmsTemplate.Exam.DomainService;
using LTMCompanyName.YoyoCmsTemplate.Authorization;
using Microsoft.AspNetCore.Mvc.Rendering;
using LTMCompanyName.YoyoCmsTemplate.Exam.Colleges.Enum;
using LTMCompanyName.YoyoCmsTemplate.Enums;

namespace LTMCompanyName.YoyoCmsTemplate.Exam
{
    /// <summary>
    /// 题库应用层服务的接口实现方法
	/// <see cref="Stock" />
    ///</summary>
    public class StockAppService : YoyoCmsTemplateAppServiceBase, IStockAppService
    {

        private readonly IRepository<Stock, long> _entityRepository;

        private readonly IStockManager _stockManager;

        private readonly IRepository<StockCategory, long> _stockCategoryRepository;

        private readonly IRepository<StockItem, long> _stockItemrepository;

        /// <summary>
        /// 构造函数
        ///</summary>

        public StockAppService(IStockManager stockManager,
            IRepository<Stock, long> entityRepository,
            IRepository<StockCategory, long> stockCategoryRepository,
             IRepository<StockItem, long> stockItemrepository
            )
        {
            _stockManager = stockManager;
            this._entityRepository = entityRepository;
            this._stockCategoryRepository = stockCategoryRepository;
            this._stockItemrepository = stockItemrepository;
        }


        /// <summary>
        /// 获取题库的分页列表信息
        ///</summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AbpAuthorize(StockPermissions.Stock_Query)]
        public async Task<PagedResultDto<StockListDto>> GetPaged(GetStocksInput input)
        {

            var query = this._entityRepository.GetAll().AsNoTracking().WhereIf(!input.FilterText.IsNullOrWhiteSpace(), a => a.Title.Contains(input.FilterText)).Where(a => a.CreatorUserId == AbpSession.UserId);
            // TODO:根据传入的参数添加过滤条件

            var count = await query.CountAsync();

            var stockList = await query
            .OrderBy(input.Sorting).AsNoTracking()
            .PageBy(input)
            .ToListAsync();

            // 包装列表需要显示的字段
            var stockListDtos = stockList.Select(item =>
            {
                return new StockListDto
                {
                    Id = item.Id,
                    Status = item.Status,
                    StatusName = ((Status)Convert.ToInt32(item.Status)).GetDescription(),
                    Title = item.Title,
                    CategoryId = item.CategoryId,
                    CategoryName = this._stockCategoryRepository.Get(item.CategoryId)?.Name,
                    Type = item.Type,
                    TypeName = ((Colleges.Enum.Type)Convert.ToInt32(item.Type)).GetDescription(),
                    Score = item.Score,
                    Limit = item.Limit,
                };
            }).ToList();


            return new PagedResultDto<StockListDto>(count, stockListDtos);
        }

        /// <summary>
        /// 获得题目
        ///</summary>
        /// <param name="CategoryId">分类id</param>
        /// <returns></returns>
        public async Task<StockListAndCategoryDto> Get(long CategoryId)
        {
            var categorymodel = this._stockCategoryRepository.Get(CategoryId);

            var query = this._entityRepository.GetAll()
                .AsNoTracking()
                .Where(a => a.CategoryId == CategoryId);

            if (categorymodel.ShowCount > 0)
                query = query.OrderBy(x => Guid.NewGuid())
                .Take(categorymodel.ShowCount);

            var stockList = await query.ToListAsync();
            //是否打乱顺序
            bool blag = categorymodel.IsUpset;
            // 包装列表需要显示的字段
            var stockListDtos = new StockListAndCategoryDto
            {
                CategoryList = categorymodel,
                StockList = stockList.Select(item =>
                  {
                      var stoitem = _stockItemrepository.GetAll()
                            .Where(x => x.StockId == item.Id)
                            .ToList();
                      if (blag)
                          stoitem.Sort((x, y) => { return new Random().Next(-1, 1); });
                      return new StockListDto
                      {
                          Id = item.Id,
                          Status = item.Status,
                          StatusName = ((Status)Convert.ToInt32(item.Status)).GetDescription(),
                          Title = item.Title,
                          CategoryId = item.CategoryId,
                          CategoryName = this._stockCategoryRepository.Get(item.CategoryId)?.Name,
                          Type = item.Type,
                          TypeName = ((Colleges.Enum.Type)Convert.ToInt32(item.Type)).GetDescription(),
                          Score = item.Score,
                          Limit = item.Limit,
                          StockItemList = stoitem,
                      };
                  }).ToList()
            };
            return stockListDtos;
        }

        /// <summary>
        /// 通过指定id获取StockListDto信息
        /// </summary>
        [AbpAuthorize(StockPermissions.Stock_Query)]
        public async Task<StockListDto> GetById(EntityDto<long> input)
        {
            var entity = await _entityRepository.GetAsync(input.Id);

            var dto = ObjectMapper.Map<StockListDto>(entity);
            return dto;
        }

        /// <summary>
        /// 获取编辑 题库
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AbpAuthorize(StockPermissions.Stock_Create, StockPermissions.Stock_Edit)]
        public async Task<GetStockForEditOutput> GetForEdit(NullableIdDto<long> input)
        {
            var output = new GetStockForEditOutput();
            StockEditDto editDto;

            if (input.Id.HasValue)
            {
                var entity = await _entityRepository.GetAsync(input.Id.Value);
                editDto = ObjectMapper.Map<StockEditDto>(entity);
                output.StockItems = this._stockItemrepository.GetAll().Where(x => x.StockId == editDto.Id).ToList();
            }
            else
            {
                editDto = new StockEditDto();
            }
            output.CategoryList = this._stockCategoryRepository.GetAllList().Where(x => x.Status == "1").Where(a => a.CreatorUserId == AbpSession.UserId).Select(a => new SelectListItem()
            {
                Text = a.Name,
                Value = a.Id.ToString()
            }).ToList();

            output.Stock = editDto;
            return output;
        }


        /// <summary>
        /// 添加或者修改题库的公共方法
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AbpAuthorize(StockPermissions.Stock_Create, StockPermissions.Stock_Edit)]
        public async Task CreateOrUpdate(CreateOrUpdateStockInput input)
        {

            if (input.Stock.Id.HasValue)
            {
                await Update(input.Stock, input.stockItems);
            }
            else
            {
                await Create(input.Stock, input.stockItems);
            }
        }


        /// <summary>
        /// 新增题库
        /// </summary>
        [AbpAuthorize(StockPermissions.Stock_Create)]
        protected virtual async Task<StockEditDto> Create(StockEditDto input, List<StockItem> stockItems)
        {
            //TODO:新增前的逻辑判断，是否允许新增

            var entity = ObjectMapper.Map<Stock>(input);
            //调用领域服务
            var id = _entityRepository.InsertAndGetId(entity);
            var dto = ObjectMapper.Map<StockEditDto>(entity);
            for (int i = 0; i < stockItems.Count(); i++)
            {
                stockItems[i].Sort = i;
                stockItems[i].StockId = id;
                await _stockItemrepository.InsertAsync(stockItems[i]);
            }
            return dto;
        }

        /// <summary>
        /// 编辑题库
        /// </summary>
        [AbpAuthorize(StockPermissions.Stock_Edit)]
        protected virtual async Task Update(StockEditDto input, List<StockItem> stockItems)
        {
            //TODO:更新前的逻辑判断，是否允许更新

            var entity = await _entityRepository.GetAsync(input.Id.Value);
            //  input.MapTo(entity);
            //将input属性的值赋值到entity中
            ObjectMapper.Map(input, entity);
            await _entityRepository.UpdateAsync(entity);

            //删除原来的 新增新的
            var listid = _stockItemrepository.GetAll().Where(x => x.StockId == input.Id).Select(x => x.Id).ToList();
            await _stockItemrepository.DeleteAsync(a => listid.Contains(a.Id));

            for (int i = 0; i < stockItems.Count(); i++)
            {
                stockItems[i].Sort = i;
                stockItems[i].StockId = entity.Id;
                await _stockItemrepository.InsertAsync(stockItems[i]);
            }
        }



        /// <summary>
        /// 删除题库信息
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        [AbpAuthorize(StockPermissions.Stock_Delete)]
        public async Task Delete(EntityDto<long> input)
        {
            //TODO:删除前的逻辑判断，是否允许删除
            await _entityRepository.DeleteAsync(input.Id);
            ////然后批量删除选项
            //var listid = _stockItemrepository.GetAll().Where(x => x.StockId == input.Id).Select(x => x.Id).ToList();
            //await _stockItemrepository.DeleteAsync(a => listid.Contains(a.Id));
        }

        /// <summary>
        /// 批量删除Stock的方法
        /// </summary>
        [AbpAuthorize(StockPermissions.Stock_BatchDelete)]
        public async Task BatchDelete(List<long> input)
        {
            // 批量删除题库
            await this._entityRepository.DeleteAsync(a => input.Contains(a.Id));
            //不用删除选项
            //var listid = _stockItemrepository.GetAll().Where(x => input.Contains(x.StockId)).Select(x => x.Id).ToList();
            //await _stockItemrepository.DeleteAsync(a => listid.Contains(a.Id));
        }

        //// custom codes
        /// <summary>
        /// 导入
        /// </summary>
        /// <returns></returns>
        [AbpAuthorize(StockPermissions.Stock_BatchDelete)]
        public async Task<string> ToExcelData(List<List<string>> ts, long categoryId)
        {
            string arr = "";
            foreach (var item in ts)
            {
                Stock stockEditDto = new Stock();
                //添加
                stockEditDto.CategoryId = categoryId;
                string answer = "";
                int number = 1;
                long id = 0;
                foreach (var a in item)
                {
                    StockItem stockItemEditDto = new StockItem();
                    if (number == 1)
                    {
                        stockEditDto.Type = a.Contains("单选") ? "1" : "2";
                    }
                    else if (number == 2)
                    {
                        stockEditDto.Title = a;
                    }
                    else if (number == 3)
                    {
                        stockEditDto.Score = Convert.ToInt32(a);
                    }
                    else if (number == 4)
                    {
                        answer = a.ToUpper();
                        stockEditDto.Status = "1";
                        stockEditDto.Limit = answer.Length;
                        id = await this._entityRepository.InsertAndGetIdAsync(stockEditDto);
                    }
                    else
                    {
                        stockItemEditDto.StockId = id;
                        stockItemEditDto.Sort = number - 4;
                        stockItemEditDto.Title = a;
                        //正确答案中是否有这一项
                        stockItemEditDto.IsRight = answer.Contains("" + (char)('A' + (number - 5)));
                        await this._stockItemrepository.InsertAsync(stockItemEditDto);
                    }
                    number++;
                }
                number = 0;
            }
            return arr;
        }
        //// custom codes end

    }
}


